import { invoke } from '@tauri-apps/api/core';
import { listen, UnlistenFn } from '@tauri-apps/api/event';

type EventCallback = (data?: any) => void;

interface ConnectionEvent {
  status: string;
  message?: string;
}

interface MessageEvent {
  message: any;
}

class WebSocketService {
  private eventListeners: Map<string, EventCallback[]> = new Map();
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 10;
  private baseReconnectDelay = 2000; // 基础重连延迟 2秒
  private maxReconnectDelay = 30000; // 最大重连延迟 30秒
  private subscriptionId: string | null = null;
  private statusListeners: UnlistenFn[] = [];
  private messageListeners: UnlistenFn[] = [];
  private isConnected = false;
  private reconnectTimer: number | null = null;
  private healthCheckTimer: number | null = null;
  private healthCheckInterval = 30000; // 健康检查间隔 30秒
  private isReconnecting = false;

  async connect(subscriptionId: string, wsUrl?: string) {
    // 验证 subscriptionId 不能为空、null 或 undefined
    if (subscriptionId == null || subscriptionId === undefined || subscriptionId.trim() === '') {
      const error = new Error('订阅ID不能为空');
      console.error('WebSocket 连接失败:', error);
      this.isConnected = false;
      this.emit('error', error);
      throw error;
    }

    // 如果已经有连接且是同一个订阅 ID，不重复连接
    if (this.isConnected && this.subscriptionId === subscriptionId) {
      console.log('WebSocket 已连接，跳过重复连接');
      return;
    }

    // 如果正在连接，先断开
    if (this.subscriptionId && this.subscriptionId !== subscriptionId) {
      await this.disconnect();
    }

    this.subscriptionId = subscriptionId;

    try {
      // 清理旧的事件监听器
      this.cleanupListeners();

      // 监听连接状态事件
      const statusUnlisten = await listen<ConnectionEvent>('websocket-status', (event) => {
        const { status, message } = event.payload;
        console.log('WebSocket 状态:', status, message);
        
        if (status === 'connected') {
          this.isConnected = true;
          this.reconnectAttempts = 0;
          this.isReconnecting = false;
          this.clearReconnectTimer();
          this.startHealthCheck();
          this.emit('connected');
        } else if (status === 'disconnected') {
          this.isConnected = false;
          this.stopHealthCheck();
          console.log('WebSocket 已断开:', message);
          this.emit('disconnected');
          // 如果断开连接且有订阅ID，尝试重连（延迟一下，避免立即重连）
          if (this.subscriptionId && !this.isReconnecting) {
            console.log('WebSocket 断开，将在 1 秒后尝试重连...');
            setTimeout(() => {
              if (this.subscriptionId && !this.isReconnecting) {
                this.attemptReconnect();
              }
            }, 1000);
          }
        } else if (status === 'error') {
          this.isConnected = false;
          this.stopHealthCheck();
          const errorMessage = message || 'WebSocket 错误';
          const error = new Error(errorMessage);
          
          // 连接被重置是正常的网络情况，会自动重连，只记录日志
          if (errorMessage.includes('连接被重置') || errorMessage.includes('connection reset')) {
            console.log('WebSocket 连接被重置，正在自动重连...');
          } else {
            console.error('WebSocket 错误:', error);
          }
          
          this.emit('error', error);
          // 如果出错且有订阅ID，尝试重连（延迟一下，避免立即重连）
          if (this.subscriptionId && !this.isReconnecting) {
            console.log('WebSocket 出错，将在 1 秒后尝试重连...');
            setTimeout(() => {
              if (this.subscriptionId && !this.isReconnecting) {
                this.attemptReconnect();
              }
            }, 1000);
          }
        } else if (status === 'connecting') {
          this.emit('connecting');
        }
      });
      this.statusListeners.push(statusUnlisten);

      // 监听消息事件
      const messageUnlisten = await listen<MessageEvent>('websocket-message', (event) => {
        console.log('🔵 [WebSocket Service] 收到 websocket-message 事件');
        console.log('🔵 [WebSocket Service] 事件 payload:', event.payload);
        const { message } = event.payload;
        console.log('🔵 [WebSocket Service] 提取的 message:', message);
        console.log('🔵 [WebSocket Service] 消息类型:', typeof message);
        console.log('🔵 [WebSocket Service] 消息键:', message && typeof message === 'object' ? Object.keys(message) : 'null');
        
        // message 可能是 JSON 对象或包含 raw 字段的对象
        if (message && typeof message === 'object' && 'raw' in message) {
          // 如果消息有raw字段，说明是原始文本
          console.log('🔵 [WebSocket Service] 消息包含 raw 字段，尝试解析');
          try {
            const parsed = JSON.parse(message.raw as string);
            console.log('🔵 [WebSocket Service] 解析后的消息:', parsed);
            console.log('🔵 [WebSocket Service] 解析后的消息 chat_type:', parsed?.chat_type);
            console.log('🔵 [WebSocket Service] 准备触发 message 事件（解析后的）');
            this.emit('message', parsed);
            console.log('🔵 [WebSocket Service] message 事件已触发（解析后的）');
          } catch (e) {
            console.error('🔴 [WebSocket Service] 解析消息失败:', e, '原始消息:', message.raw);
            // 如果解析失败，尝试直接发送原始消息
            console.log('🔵 [WebSocket Service] 准备触发 message 事件（原始消息）');
            this.emit('message', message);
            console.log('🔵 [WebSocket Service] message 事件已触发（原始消息）');
          }
        } else {
          // 直接发送消息对象
          console.log('🔵 [WebSocket Service] 直接发送消息对象，chat_type:', message?.chat_type);
          console.log('🔵 [WebSocket Service] 消息对象详情:', {
            message_id: message?.message_id,
            from_user_id: message?.from_user_id,
            to_user_id: message?.to_user_id,
            chat_type: message?.chat_type,
            message: message?.message?.substring?.(0, 50),
          });
          console.log('🔵 [WebSocket Service] 准备触发 message 事件（直接对象）');
          this.emit('message', message);
          console.log('🔵 [WebSocket Service] message 事件已触发（直接对象）');
        }
      });
      this.messageListeners.push(messageUnlisten);
      console.log('✅ [WebSocket Service] websocket-message 事件监听器已设置');

      // 获取 token
      const { storageGet, isTauri } = await import('./secure-storage');
      const token = isTauri()
        ? await storageGet('token')
        : localStorage.getItem('token');
      
      if (!token) {
        const error = new Error('未找到认证 token，请重新登录');
        console.error('WebSocket 连接失败:', error);
        this.isConnected = false;
        this.emit('error', error);
        throw error;
      }
      
      // 调用 Rust 命令连接 WebSocket
      const { WS_URL } = await import('@/config/env');
      const defaultUrl = `${WS_URL}/ws/${subscriptionId}`;
      await invoke('connect_websocket', {
        subscriptionId,
        wsUrl: wsUrl || defaultUrl,
        token: token,
      });

      console.log('WebSocket 连接请求已发送');
    } catch (error) {
      console.error('WebSocket 连接失败:', error);
      this.isConnected = false;
      this.emit('error', error);
      throw error;
    }
  }

  async disconnect() {
    try {
      // 停止所有重连尝试
      this.clearReconnectTimer();
      this.stopHealthCheck();
      this.isReconnecting = false;
      
      // 保存 subscriptionId，以便后续可能需要重连
      const savedSubscriptionId = this.subscriptionId;
      
      // 断开连接
      try {
        await invoke('disconnect_websocket');
      } catch (error) {
        console.warn('断开 WebSocket 时出错（可能已经断开）:', error);
      }
      
      this.cleanupListeners();
      // 注意：不清空 subscriptionId，以便需要时可以重连
      // this.subscriptionId = null;
      this.isConnected = false;
      this.reconnectAttempts = 0;
      console.log('WebSocket 已断开');
    } catch (error) {
      console.error('断开 WebSocket 失败:', error);
      // 即使断开失败，也更新状态
      this.isConnected = false;
      this.isReconnecting = false;
      throw error;
    }
  }
  
  // 完全断开连接（不清空 subscriptionId，允许后续重连）
  async forceDisconnect() {
    await this.disconnect();
  }
  
  // 完全清理（清空 subscriptionId，不允许重连）
  async cleanup() {
    await this.disconnect();
    this.subscriptionId = null;
  }

  async send(data: any) {
    if (!this.isConnected) {
      console.error('WebSocket 未连接');
      throw new Error('WebSocket 未连接');
    }

    try {
      const message = typeof data === 'string' ? data : JSON.stringify(data);
      await invoke('send_websocket_message', { message });
    } catch (error) {
      console.error('发送消息失败:', error);
      throw error;
    }
  }

  async getStatus(): Promise<string | null> {
    try {
      const status = await invoke<string>('get_websocket_status');
      return status;
    } catch (error) {
      console.error('获取连接状态失败:', error);
      return null;
    }
  }

  on(event: string, callback: EventCallback) {
    if (!this.eventListeners.has(event)) {
      this.eventListeners.set(event, []);
    }
    this.eventListeners.get(event)!.push(callback);
  }

  off(event: string, callback: EventCallback) {
    const callbacks = this.eventListeners.get(event);
    if (callbacks) {
      const index = callbacks.indexOf(callback);
      if (index > -1) {
        callbacks.splice(index, 1);
      }
    }
  }

  private emit(event: string, data?: any) {
    const callbacks = this.eventListeners.get(event);
    if (callbacks) {
      callbacks.forEach(callback => callback(data));
    }
  }

  // 公共方法：触发事件（用于外部触发自定义事件）
  public trigger(event: string, data?: any) {
    this.emit(event, data);
  }

  private cleanupListeners() {
    // 清理所有事件监听器
    this.statusListeners.forEach(unlisten => unlisten());
    this.messageListeners.forEach(unlisten => unlisten());
    this.statusListeners = [];
    this.messageListeners = [];
  }

  private async attemptReconnect() {
    if (this.isReconnecting) {
      console.log('正在重连中，跳过重复重连请求');
      return;
    }

    // 重置重连次数限制，允许无限重连（但使用指数退避）
    // 只有在用户主动断开时才停止重连
    if (!this.subscriptionId) {
      console.warn('没有订阅ID，无法重连');
      this.isReconnecting = false;
      return;
    }

    this.isReconnecting = true;
    this.reconnectAttempts++;
    
    // 指数退避策略：延迟时间 = baseDelay * 2^(attempts-1)，但不超过 maxDelay
    // 对于前几次重连，使用较短的延迟
    let delay = this.baseReconnectDelay;
    if (this.reconnectAttempts > 1) {
      delay = Math.min(
        this.baseReconnectDelay * Math.pow(2, Math.min(this.reconnectAttempts - 1, 5)), // 最多2^5=32倍
        this.maxReconnectDelay
      );
    }

    console.log(`将在 ${delay}ms 后尝试重连 (第 ${this.reconnectAttempts} 次)...`);

    this.reconnectTimer = window.setTimeout(async () => {
      try {
        // 检查 subscriptionId 是否存在
        if (!this.subscriptionId) {
          console.warn('重连失败: 订阅ID为空');
          this.isReconnecting = false;
          return;
        }
        
        // 先检查当前状态，如果已经连接则不需要重连
        const currentStatus = await this.getStatus();
        if (currentStatus === 'connected') {
          console.log('连接已恢复，取消重连');
          this.isConnected = true;
          this.isReconnecting = false;
          this.reconnectAttempts = 0;
          this.startHealthCheck();
          return;
        }
        
        console.log(`尝试重连 (第 ${this.reconnectAttempts} 次)...`);
        await this.connect(this.subscriptionId);
        // 如果连接成功，isReconnecting 会在 connected 事件中重置
      } catch (error) {
        console.error(`重连失败 (第 ${this.reconnectAttempts} 次):`, error);
        this.isReconnecting = false;
        // 如果重连失败，继续尝试（无限重连，直到成功或用户主动断开）
        if (this.subscriptionId) {
          // 等待一小段时间后再次尝试
          await new Promise(resolve => setTimeout(resolve, 1000));
          this.attemptReconnect();
        }
      }
    }, delay);
  }

  private clearReconnectTimer() {
    if (this.reconnectTimer !== null) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = null;
    }
  }

  private startHealthCheck() {
    this.stopHealthCheck(); // 先清除旧的定时器
    
    this.healthCheckTimer = window.setInterval(async () => {
      if (!this.subscriptionId) {
        this.stopHealthCheck();
        return;
      }

      try {
        const status = await this.getStatus();
        // 如果状态不是 connected，且当前标记为已连接，说明连接已断开
        if (status !== 'connected' && this.isConnected) {
          console.warn('健康检查发现连接断开，状态:', status, '尝试重连...');
          if (!this.isReconnecting && this.subscriptionId) {
            this.isConnected = false;
            this.reconnectAttempts = 0; // 重置重连次数，给重连机制一个机会
            this.attemptReconnect();
          }
        }
        // 如果状态是 connected，但当前标记为未连接，更新状态
        if (status === 'connected' && !this.isConnected) {
          console.log('健康检查发现连接已恢复');
          this.isConnected = true;
          this.reconnectAttempts = 0;
          this.isReconnecting = false;
          this.clearReconnectTimer();
        }
      } catch (error) {
        console.error('健康检查失败:', error);
        // 健康检查失败也可能意味着连接断开
        if (!this.isReconnecting && this.subscriptionId && this.isConnected) {
          console.warn('健康检查异常，尝试重连...');
          this.isConnected = false;
          this.reconnectAttempts = 0;
          this.attemptReconnect();
        }
      }
    }, this.healthCheckInterval);
  }

  private stopHealthCheck() {
    if (this.healthCheckTimer !== null) {
      clearInterval(this.healthCheckTimer);
      this.healthCheckTimer = null;
    }
  }
}

export default new WebSocketService();

